<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app"></div>
    <script>
      // 定义一个副作用函数桶
      const bucket = new Set();

      // 定义一个全局变量，保存当前正在执行的副作用函数
      let activeEffect = null

      function isObject(value) {
        return typeof value === "object" && value !== null;
      }

      function reactive(data) {
        if (!isObject) return;

        return new Proxy(data, {
          get(target, key) {
            activeEffect && bucket.add(activeEffect)
            return target[key];
          },
          set(target, key, value) {
            target[key] = value;
            // 调用副作用函数
            bucket.forEach((fn) => fn());
            return true;
          },
        });
      }
      /**
       * 注册副作用函数
       * @param {*} fn
      */
      function registEffect(fn) {
        if(typeof fn !=="function") return
        // 记录正在执行的副作用函数
        activeEffect = fn
        // 调用
        fn()
        // 重置全局变量
        activeEffect = null
      }
      const state = { name: "孙悟空", age: 18 };
      // 定义一个变量，触发者
      const proxy = reactive(state);

      // 定义一个函数，响应者
      function effectName() {
        app.innerHTML = proxy.name;
      }
      registEffect(effectName)

      function effectAge() {
        console.log('effectAge被执行了...', proxy.age)
      }
      registEffect(effectAge)

      // 模拟数据的改变
      setTimeout(() => {
        proxy.name = "猪八戒";
      }, 1000);
      console.log('bucket', bucket)
      /*
        问题：属性名---对应的副作用函数 这种映射关系用Set结构还无法满足，
        思路：可以利用Map结构对桶进行改造。
      */
    </script>
  </body>
</html>
